package com.dragon.app.um.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.dragon.app.commons.dto.SendSMSDTO;
import com.dragon.app.um.vo.JsonResult;
import com.dragon.common.constant.Constant;
import com.dragon.common.util.NECaptchaVerifier;
import com.dragon.common.util.NESecretPair;
import com.dragon.loan.entity.CmAttachment;
import com.dragon.loan.repository.AcLoanApplyInfoRepository;
import com.dragon.loan.service.CmAttachmentIDragonService;
import com.dragon.rabbitmq.SharedDataMqProvideApiCore;
import com.dragon.rabbitmq.dto.EdcSharedDataDTO;
import com.dragon.web.commons.utils.FileUtils;
import com.dragon.web.commons.utils.ImageUtils;
import com.fintech.common.entity.MaintenanceResult;
import com.fintech.common.entity.ResultData;
import com.fintech.common.enums.HearderName;
import com.fintech.common.enums.RespStatus;
import com.fintech.common.enums.ResultCode;
import com.fintech.common.enums.ReturnCode;
import com.fintech.common.util.MaintenanceUtils;
import com.fintech.common.util.RedisUtils;
import com.fintech.common.util.ShaUtil;
import com.fintech.common.vo.FintechResult;
import com.fintech.third.constant.ResponseResult;
import com.fintech.third.constant.SmsTypeEnum;
import com.fintech.third.model.facerecog.FaceCompareResponse;
import com.fintech.third.service.BaseServiceUtil;
import com.fintech.third.service.BurialPointService;
import com.fintech.third.service.facerecog.FaceRecognitionService;
import com.fintech.third.service.sms.SmsService;
import com.fintech.third.utils.PropertisLoadUtil;
import com.fintech.user.entity.RealNameAuthAndFaceCompare;
import com.fintech.user.entity.RealNameAuthentication;
import com.fintech.user.entity.User;
import com.fintech.user.entity.UserChannelInfo;
import com.fintech.user.service.RealNameAuthenticationService;
import com.fintech.user.service.UserChannelInfoService;
import com.fintech.user.service.UserService;
import com.marvels.approve.loan.dao.IMcamLoanApplyInfoDao;
import com.marvels.common.utils.MarvelsLogUtil;
import com.marvels.common.utils.ServerProperties;

import cn.hutool.core.bean.BeanUtil;
import net.sf.json.JSONObject;

/**
 * 
 * @author liuxy
 *
 */
@Service("clientUserAppService")
public class ClientUserServiceImpl implements ClientUserService {

	@Autowired
	private UserService userService;
	@Autowired
	private RealNameAuthenticationService realNameAuthenticationService;
	@Autowired
	private FaceRecognitionService faceRecognitionService;
	@Autowired
	private SmsService smsService;
	@Autowired
	private BurialPointService burialPointService;
	@Autowired
	private UserChannelInfoService userChannelInfoService;
	@Autowired
	private CmAttachmentIDragonService cmAttachmentService;
	@Autowired
	private BaseServiceUtil baseServiceUtil;
	@Autowired
	private SharedDataMqProvideApiCore sharedDataMqProvideApi;
	@Autowired
	private AcLoanApplyInfoRepository acLoanApplyInfoRepository;
	@Autowired
	private IMcamLoanApplyInfoDao mcamLoanApplyInfoDao ;
	@Value("${config.properties.path}")
	private  String configPropertiesPath;
	
	
	@Transactional
	@Override
	public FintechResult addRealNameAuthAndFaceCompare(RealNameAuthAndFaceCompare reqDto, User user) {
		MarvelsLogUtil.getInstance().info("======有盾实名认证和人脸视别入库（只有全部通过后才调用该方法），参数:" + reqDto);
		try {
			if (reqDto == null || StringUtils.isEmpty(reqDto.getIdentityCardNo())) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "身份证信息为空");
			}

			// 防止并发
			if (!RedisUtils.getInstance().isLockSuccess(user.getMobileNo() + "addRealNameAuthAndFaceCompare",
					"addRealNameAuthAndFaceCompare")) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "正在人脸视别中!");
			}
			RedisUtils.getInstance().expire(user.getMobileNo() + "addRealNameAuthAndFaceCompare", 30);// 设置失效时间

			// 判断用户有没有做过实名认证
			RealNameAuthentication realNameAuthenticationDb = realNameAuthenticationService.queryByUserId(user.getId());
			if (realNameAuthenticationDb != null) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "您已做过实名认证");
			}

			// 判断传过来的身份证号码有没有做过实名认证
			realNameAuthenticationDb = realNameAuthenticationService.querByIdentiyCardNo(reqDto.getIdentityCardNo());
			if (realNameAuthenticationDb != null) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(),
						"身份证号[" + reqDto.getIdentityCardNo() + "]已被实名认证");
			}
			reqDto.setUserId(user.getId());
			reqDto.setLastFaceCheckDate(new Date());
			reqDto.setFaceCheckTimes(0);
			reqDto.setFaceTag("1");

			// 人脸识别保存头像
			saveImg(reqDto.getPictureBase64(), user.getMobileNo());

			// 保存实名认证信息
			RealNameAuthentication realNameAuthentication = new RealNameAuthentication();
			BeanUtil.copyProperties(reqDto, realNameAuthentication);
			ResultData<Boolean> resultDataReal = realNameAuthenticationService
					.addRealNameAuthentication(realNameAuthentication);
			if (!StringUtils.equals(ReturnCode.success.getErrorCode(), resultDataReal.getResultCode())) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "保存实名认证信息失败");
			}
			
			// 刷新用户REDIS缓存信息
			freshUser(realNameAuthentication, user);

			// 更新用户表状态（实名认证标识）
			MarvelsLogUtil.getInstance().info("开始更新用户表");
			User userParam = new User();
			userParam.setId(user.getId());
			userParam.setIdFintechUmUser(user.getIdFintechUmUser());
			userParam.setIsVerify(1);
			userParam.setIsFace(1);
			userParam.setRealName(reqDto.getRealName());
			userParam.setCardNo(reqDto.getIdentityCardNo());
			userService.modifyUser(userParam);

			MarvelsLogUtil.getInstance().info("======有盾实名认证和人脸视别入库成功");
			return FintechResult.getSuccessResult(realNameAuthentication);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("有盾实名认证和人脸视别入库异常, reqDto=[" + reqDto + "]", e);
			return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "有盾实名认证和人脸视别入库异常");
		}
	}
	

	@Override
	public JsonResult<User> login(User user, Map<String, String> headers, String ipAddress) {
		JsonResult<User> result = new JsonResult<User>();

		// 1 如果设备校验开关打开并且校验失败，则不允许登录
		String deviceSwitch = PropertisLoadUtil.getPropertiesValue("device.validate.switch", "common.properties");
		if (Constant.USER_LOGIN_DEVICE_VALID_SWITCH_ON.equals(deviceSwitch) && !userService.validateDevice(user)) {
			result.setErrorMsg("请使用客户本人手机登录");
			return result;
		}

		Map<String, String> map = new HashMap<>();
		ResultData<User> resultData = null;

		// 2 调用um服务登录
		try {
			if (StringUtils.isEmpty(user.getUserType())) {// 默认设置为客户
				user.setUserType(Constant.USER_TYPE_CUSTOMER);
			}
			resultData = userService.login(user);
			if (!ResultCode.success.getResultCode().equals(resultData.getResultCode())) {
				result.setErrorMsg(resultData.getMessage());
				return result;
			}

			// 2.1 登录成功后获取登录信息回填到返回实体
			StringBuilder sb = new StringBuilder();
			sb.append(resultData.getData().getIdFintechUmUser())
					.append(headers.get(HearderName.appVersion.getHeaderName()))
					.append(headers.get(HearderName.timeStamp.getHeaderName()))
					.append(headers.get(HearderName.appKey.getHeaderName())).append(System.currentTimeMillis());
			String token = ShaUtil.Encrypt(sb.toString(), "");
			resultData.getData().setToken(token);
			result.setData(resultData.getData());

			// 2.2 登录成功后将实名认证信息填充到返回信息
			RealNameAuthentication realNameAuthentication = realNameAuthenticationService
					.queryByUserId(resultData.getData().getId());
			if (realNameAuthentication != null) {
				resultData.getData().setRealName(realNameAuthentication.getRealName());
				resultData.getData().setCardNo(realNameAuthentication.getIdentityCardNo());
				resultData.getData().setRealNameAuthentication(true);
				resultData.getData().setFaceCheck(false);
				map.put("idNo", realNameAuthentication.getIdentityCardNo());
				Integer faceTag = realNameAuthenticationService.findByUserId(resultData.getData().getId());
				if (faceTag == 0) {
					resultData.getData().setFaceCheck(true);
				}
			} else {
				resultData.getData().setRealNameAuthentication(false);
				resultData.getData().setFaceCheck(false);
			}

			// 这段代码为测试代码，就是配置的白名单不需要验证
			String testAccount = PropertisLoadUtil
					.getPropertiesValue("not.valid.deviceId.mobileno", "common.properties").trim();
			boolean isValidDeviceId = true;// 默认需要验证设备
			if (StringUtils.isNotEmpty(testAccount)) {
				String[] testAccounts = testAccount.split(",");
				isValidDeviceId = !Arrays.asList(testAccounts).contains(user.getMobileNo());
			}

			// 3 校验
			if (StringUtils.isNotEmpty(resultData.getData().getDeviceId()) && isValidDeviceId) {
				if (StringUtils.isEmpty(user.getValidCode())) {// 3.1 验证设备时验证码为空
					// 设备验证
					if (!StringUtils.equals(resultData.getData().getDeviceId(), user.getDeviceId())) {
						String mobileNo = user.getMobileNo();
						// 3.1.2 发送短信验证码
						ResponseResult responseResult = smsService.sendSms(mobileNo, null, SmsTypeEnum.REGISTER);
						MarvelsLogUtil.getInstance().info("发送结果##resultMsg>>>>"+JSON.toJSONString(responseResult));
						if ((RespStatus.SUCCESS.getCode() + "").equals(responseResult.getErrorCode())) {
							result.setData(null);
							result.setMessage("");
							result.setErrorCode("3");
							return result;
						} else {
							result.setData(null);
							result.setErrorCode(ReturnCode.fail.getErrorCode());
							result.setErrorMsg("设备不一致，短信发送失败");
							return result;
						}
					}
				} else {// 3.2 验证码校验
					if (!smsService.checkCode(user.getMobileNo(), user.getValidCode(), SmsTypeEnum.REGISTER.getName())) {
						result.setData(null);
						result.setErrorCode("-2");
						result.setMessage("验证码不正确!");
						return result;
					}
				}
			}

			// 4 缓存登录信息（15天有效）
			String redisResult = RedisUtils.getInstance().setex(resultData.getData().getIdFintechUmUser(),
					15 * 24 * 60 * 60, JSONObject.fromObject(resultData.getData()).toString());// 15天有效
			MarvelsLogUtil.getInstance().info("redisResult===>>" + redisResult);
			if ("0".equals(redisResult)) {
				result.setErrorMsg("登录异常(redis缓存失败)!");
				return result;
			}

		} catch (Exception e) {
			result.setErrorMsg("登录失败!");
			MarvelsLogUtil.getInstance().error("clientUser_login==>>", e);
			return result;
		}

		// 5 更新设备号和客户端ID
		try {
			if (StringUtils.isNotEmpty(user.getCid())// 5.1 更新客户端ID
					&& !StringUtils.equalsIgnoreCase(resultData.getData().getCid(), user.getCid())) {
				User userParam = new User();
				userParam.setId(resultData.getData().getId());
				userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
				userParam.setCid(user.getCid());
				userService.modifyUser(userParam);
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_login_cid==>>", e);
		}

		// 5.2 更新设备号
		try {
			if (!StringUtils.equals(resultData.getData().getDeviceId(), user.getDeviceId())) {
				User userParam = new User();
				userParam.setId(resultData.getData().getId());
				userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
				userParam.setDeviceId(user.getDeviceId());
				userParam.setIsDownloadApp(1);
				userService.modifyUser(userParam);
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_login_deviceId", e);
			result.setMessage("设备号存入失败!");
		}
		
		// 5.2 更新下载标识
		try {
			User userParam = new User();
			userParam.setId(resultData.getData().getId());
			userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
			userParam.setIsDownloadApp(1);
			userService.modifyUser(userParam);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_login_IsDownloadApp", e);
			result.setMessage("下载标识存入失败!");
		}

		// 6 记录登陆信息，失败不影响原来流程
		try {
			map.put("deviceId", user.getDeviceId());
			map.put("deviceBrand", user.getDeviceBrand());
			map.put("deviceType", user.getDeviceType());
			map.put("mobileNo", user.getMobileNo());

			map.put("userId", resultData.getData().getId() + "");
			burialPointService.addUserLogin(map);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("记录登陆信息失败", e);
		}
		return result;
	}
	
	
	@Override
	public JsonResult<User> loginV2(User user, Map<String, String> headers, String ipAddress) {
		JsonResult<User> result = new JsonResult<User>();
		// 1 如果设备校验开关打开并且校验失败，则不允许登录
		String deviceSwitch = PropertisLoadUtil.getPropertiesValue("device.validate.switch", "common.properties");
		if (Constant.USER_LOGIN_DEVICE_VALID_SWITCH_ON.equals(deviceSwitch) && !userService.validateDevice(user)) {
			result.setErrorMsg("请使用客户本人手机登录");
			return result;
		}

		Map<String, String> map = new HashMap<>();
		ResultData<User> resultData = null;

		// 2 调用um服务登录
		try {
			if (StringUtils.isEmpty(user.getUserType())) {// 默认设置为客户
				user.setUserType(Constant.USER_TYPE_CUSTOMER);
			}
			resultData = userService.loginV2(user);
			
			if (!ResultCode.success.getResultCode().equals(resultData.getResultCode())) {
				result.setErrorMsg(resultData.getMessage());
				return result;
			}

			// 2.1 登录成功后获取登录信息回填到返回实体
			StringBuilder sb = new StringBuilder();
			sb.append(resultData.getData().getIdFintechUmUser())
					.append(headers.get(HearderName.appVersion.getHeaderName()))
					.append(headers.get(HearderName.timeStamp.getHeaderName()))
					.append(headers.get(HearderName.appKey.getHeaderName())).append(System.currentTimeMillis());
			String token = ShaUtil.Encrypt(sb.toString(), "");
			resultData.getData().setToken(token);
			result.setData(resultData.getData());

			// 2.2 登录成功后将实名认证信息填充到返回信息
			RealNameAuthentication realNameAuthentication = realNameAuthenticationService
					.queryByUserId(resultData.getData().getId());
			if (realNameAuthentication != null) {
				resultData.getData().setRealName(realNameAuthentication.getRealName());
				resultData.getData().setCardNo(realNameAuthentication.getIdentityCardNo());
				resultData.getData().setRealNameAuthentication(true);
				resultData.getData().setFaceCheck(false);
				map.put("idNo", realNameAuthentication.getIdentityCardNo());
				Integer faceTag = realNameAuthenticationService.findByUserId(resultData.getData().getId());
				if (faceTag == 0) {
					resultData.getData().setFaceCheck(true);
				}
			} else {
				resultData.getData().setRealNameAuthentication(false);
				resultData.getData().setFaceCheck(false);
			}

			// 4 缓存登录信息（15天有效）
			String redisResult = RedisUtils.getInstance().setex(resultData.getData().getIdFintechUmUser(),
					15 * 24 * 60 * 60, JSONObject.fromObject(resultData.getData()).toString());// 15天有效
			MarvelsLogUtil.getInstance().info("redisResult===>>" + redisResult);
			if ("0".equals(redisResult)) {
				result.setErrorMsg("登录异常(redis缓存失败)!");
				return result;
			}

		} catch (Exception e) {
			result.setErrorMsg("登录失败!");
			MarvelsLogUtil.getInstance().error("clientUser_loginV2==>>", e);
			return result;
		}

		// 5 更新设备号和客户端ID
		try {
			if (StringUtils.isNotEmpty(user.getCid())// 5.1 更新客户端ID
					&& !StringUtils.equalsIgnoreCase(resultData.getData().getCid(), user.getCid())) {
				User userParam = new User();
				userParam.setId(resultData.getData().getId());
				userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
				userParam.setCid(user.getCid());
				userService.modifyUser(userParam);
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_loginV2_cid==>>", e);
		}

		// 5.2 更新设备号
		try {
			if (!StringUtils.equals(resultData.getData().getDeviceId(), user.getDeviceId())) {
				User userParam = new User();
				userParam.setId(resultData.getData().getId());
				userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
				userParam.setDeviceId(user.getDeviceId());
				userParam.setIsDownloadApp(1);
				userService.modifyUser(userParam);
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_loginV2_deviceId", e);
			result.setMessage("设备号存入失败!");
		}
		
		// 5.2 更新下载标识
		try {
			User userParam = new User();
			userParam.setId(resultData.getData().getId());
			userParam.setIdFintechUmUser(resultData.getData().getIdFintechUmUser());
			userParam.setIsDownloadApp(1);
			userService.modifyUser(userParam);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("clientUser_loginV2_IsDownloadApp", e);
			result.setMessage("下载标识存入失败!");
		}

		// 6 记录登陆信息，失败不影响原来流程
		try {
			map.put("deviceId", user.getDeviceId());
			map.put("deviceBrand", user.getDeviceBrand());
			map.put("deviceType", user.getDeviceType());
			map.put("mobileNo", user.getMobileNo());
			map.put("userId", resultData.getData().getId() + "");
			burialPointService.addUserLogin(map);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("记录登陆信息失败", e);
		}
		return result;
	}
	
	/**
	 * 实名认证
	 */
	@Override
	public JsonResult<String> addRealNameAuthentication(String idFintechUmUser, String accessToken,
			RealNameAuthentication realNameAuthentication) {
		JsonResult<String> jsonResult = new JsonResult<String>();

		// 1 先判断是否公安部系统是否正常
		/**
		 * ADD BY TUXU 公安部系统升级，导致身份证验证及人脸比对无法使用，加挂一个提示
		 */
		MaintenanceResult result = MaintenanceUtils.getMaintenance("gongan");
		if (result.isMaintenance()) {
			jsonResult.setErrorMsg("服务维护升级中，请于" + result.getEndTime() + "后重试");
			return jsonResult;
		}

		if (realNameAuthentication == null) {
			jsonResult.setErrorMsg("参数有误!");
			return jsonResult;
		}

		User user = null;
		try {
			// 2 校验 身份证号码非空，是否已经实名认证过等
			ResultData<?> resultData = RedisUtils.verifyUser(accessToken, idFintechUmUser, User.class);
			if (!resultData.getResultCode().equals(ReturnCode.success.getErrorCode())) {
				jsonResult.setErrorMsg(resultData.getMessage());
				return jsonResult;
			}
			user = (User) resultData.getData();// 2.1 身份证号码非空
			if (StringUtils.isEmpty(realNameAuthentication.getIdentityCardNo())) {
				jsonResult.setErrorMsg("身份证号码为空!");
				return jsonResult;
			}

			// 2.2 防止并发
			if (!RedisUtils.getInstance().isLockSuccess(user.getMobileNo() + "addRealNameAuthentication",
					"addRealNameAuthentication")) {
				jsonResult.setErrorMsg(ReturnCode.fail.getErrorCode(), "正在实名认证中!");
				return jsonResult;
			}
			RedisUtils.getInstance().expire(user.getMobileNo() + "addRealNameAuthentication", 30);// 设置失效时间

			RealNameAuthentication realNameAuthenticationDb = null;// 2.3
																	// 已经实名认证过
			realNameAuthenticationDb = realNameAuthenticationService.queryByUserId(user.getId());
			if (realNameAuthenticationDb != null) {
				jsonResult.setErrorMsg("2", "您已实名认证!");
				return jsonResult;
			}

			realNameAuthenticationDb = realNameAuthenticationService// 2.4
																	// 身份证号码已经认证过
					.querByIdentiyCardNo(realNameAuthentication.getIdentityCardNo());
			if (realNameAuthenticationDb != null) {
				jsonResult.setErrorMsg("1", "身份证号已被实名认证!");
				return jsonResult;
			}
			realNameAuthentication.setUserId(user.getId());

			// 3 实名认证：判断用户的身份证的姓名和身份证号和公安部的是否对的上
			Map<String, String> idCardParam = new HashMap<String, String>();
			idCardParam.put("idNumber", realNameAuthentication.getIdentityCardNo());
			idCardParam.put("userName", realNameAuthentication.getRealName());
			idCardParam.put("loanId", "");
			FaceCompareResponse idNumberVerification = faceRecognitionService.idNumberVerification(idCardParam);
			if (idNumberVerification.getErrorCode() == 0) {
				if (!idNumberVerification.isTrue) {
					jsonResult.setErrorMsg("身份证号与客户姓名不相符!");
					return jsonResult;
				}
			} else {
				jsonResult.setErrorMsg("身份证服务出了异常!");
				return jsonResult;
			}

			// 4 设置实名认证身份证正反面图像（便于人工审核）
			String idCardImage = PropertisLoadUtil.getPropertiesValue("idCardImage", "common.properties");
			if (StringUtils.isEmpty(realNameAuthentication.getIdcardimg1())) {
				realNameAuthentication.setIdcardimg1(idCardImage + realNameAuthentication.getIdcardimg1());
			}
			if (StringUtils.isEmpty(realNameAuthentication.getIdcardimg2())) {
				realNameAuthentication.setIdcardimg2(idCardImage + realNameAuthentication.getIdcardimg2());
			}

			// 5 保存实名认证信息
			ResultData<Boolean> resultDataReal = realNameAuthenticationService
					.addRealNameAuthentication(realNameAuthentication);
			if (!StringUtils.equals(ReturnCode.success.getErrorCode(), resultDataReal.getResultCode())) {
				jsonResult.setErrorMsg(resultDataReal.getMessage());
			}

			// 6 更新用户表状态（实名认证标识）
			MarvelsLogUtil.getInstance().info("开始更新实名认证标识");
			User userParam = new User();
			userParam.setId(user.getId());
			userParam.setIdFintechUmUser(idFintechUmUser);
			userParam.setIsVerify(1);
			userParam.setRealName(realNameAuthentication.getRealName());
			userParam.setCardNo(realNameAuthentication.getIdentityCardNo());
			userService.modifyUser(userParam);
		} catch (Exception e) {
			jsonResult.setErrorMsg("实名认证失败!");
			MarvelsLogUtil.getInstance().error("addRealNameAuthentication error===>>", e);
		} finally {
			RedisUtils.getInstance().del(user.getMobileNo() + "addRealNameAuthentication");
		}

		MarvelsLogUtil.getInstance().info("addRealNameAuthentication result===>>" + JSONObject.fromObject(jsonResult));
		return jsonResult;
	}
	
	@Override
	public JsonResult<Boolean> validAccountRegister(User user) {
		JsonResult<Boolean> jsonResult = new JsonResult<Boolean>();
		ResultData<Boolean> resultData = userService.validAccountRegister(user.getMobileNo(), user.getUserType());
		if (!ResultCode.success.getResultCode().equals(resultData.getResultCode())) {
			jsonResult.setErrorMsg(resultData.getMessage());
			return jsonResult;
		}
		// 存在用户信息并且密码为空，需要跳转到设置密码页面
		User userDto = userService.queryUserByMobileNo(user.getMobileNo(), user.getUserType());
		if (userDto != null && StringUtils.isEmpty(userDto.getPassWord())) {
			jsonResult.setErrorMsg("-5", "需要设置密码信息");
			return jsonResult;
		}
		jsonResult.setData(resultData.getData());
		return jsonResult;
	}
	
	/**
	 * 用户注册
	 */
	@Override
	public JsonResult<User> registerClient(User user, Map<String, String> headers, String channelName) {
		JsonResult<User> result = new JsonResult<User>();

		try {
			// 1.校验
			if (null == user || StringUtils.isEmpty(user.getMobileNo())) {// 1.1
																			// 手机号非空校验
				result.setErrorMsg(ReturnCode.fail.getErrorCode(), "手机号为空!");
				return result;
			}

			if (!smsService.checkCode(user.getMobileNo(), user.getValidCode(), SmsTypeEnum.REGISTER.getName())) {
				result.setErrorMsg(ReturnCode.fail.getErrorCode(), "验证码不正确!");
				return result; 
			}

			if (null == user || StringUtils.isEmpty(user.getPassWord())) {// 1.3
				// 默认密码为手机号后6位数
				user.setPassWord(ShaUtil.Encrypt(user.getMobileNo().substring(5 ,11), ""));
				/*result.setErrorMsg(ReturnCode.fail.getErrorCode(), "登录密码为空!");*/
			}

			// 1.4 重复提交注册校验，防止并发
			if (!RedisUtils.getInstance().isLockSuccess(user.getMobileNo() + "clientRegister", "clientRegister")) {
				result.setErrorMsg(ReturnCode.fail.getErrorCode(), "该手机号正在注册中!");
				return result;
			}
			RedisUtils.getInstance().expire(user.getMobileNo() + "clientRegister", 30);

			// 2 如果是百融渠道过来注册，验证token值
			if (StringUtils.isNotEmpty(user.getSource())) {
				//校验渠道号
				UserChannelInfo userChannelInfo = userChannelInfoService.selectChannelInfoByCode(user.getSource());
				MarvelsLogUtil.getInstance().info("=========用户注册userChannelInfo：" + com.alibaba.fastjson.JSONObject.toJSONString(userChannelInfo));
				if(userChannelInfo != null && userChannelInfo.getStatus() == 1){
					user.setChannelCode(userChannelInfo.getChannelCode());// 注册时保存外部渠道号
					user.setChannelName(userChannelInfo.getChannelName());
				}
				
				user.setChannelCodeSummary(user.getSource());// 并保存摘要部分
			}

			// 3 注册
			//user.setChannelName(channelName);
			ResultData<User> userInfo = userService.clientRegisterUser(user);
			RedisUtils.getInstance().del(user.getMobileNo() + "clientRegister");

			// 4 缓存登录后信息（15天有效）
			if (null != userInfo
					&& StringUtils.equalsIgnoreCase(userInfo.getResultCode(), ResultCode.success.getResultCode())) {
				StringBuilder sb = new StringBuilder();
				sb.append(userInfo.getData().getIdFintechUmUser())
						.append(headers.get(HearderName.appVersion.getHeaderName()))
						.append(headers.get(HearderName.timeStamp.getHeaderName()))
						.append(headers.get(HearderName.appKey.getHeaderName()));

				String token = ShaUtil.Encrypt(sb.toString(), "");
				RedisUtils.getInstance().setex(token, 15 * 24 * 60 * 60,
						JSONObject.fromObject(userInfo.getData()).toString());// 15天有效
				userInfo.getData().setToken(token);

				result.setErrorMsg(userInfo.getResultCode(), userInfo.getMessage());
				result.setData(userInfo.getData());
				
				//进件成功推送共享数据
				try {
					EdcSharedDataDTO  dataDTO=new EdcSharedDataDTO();
					dataDTO.setCreatedBy("system");
					dataDTO.setCreatedDate(new Date());
					dataDTO.setMobileNo(user.getMobileNo());
					dataDTO.setStatus("1");//注册
					dataDTO.setUpdatedDate(new Date());
					dataDTO.setUpdatedBy("system");
					sharedDataMqProvideApi.synSharedDataAdd(dataDTO);
				} catch (Exception e) {
					MarvelsLogUtil.getInstance().error(">>>>>>mobile"+user.getMobileNo()+"进件成功推送共享数据失败:",e);
				}
			} else {
				result.setErrorMsg(userInfo.getResultCode(), userInfo.getMessage());
				result.setData(userInfo.getData());

			}
		} catch (Exception e) {
			result.setErrorMsg(ReturnCode.fail.getErrorCode(), "注册失败");
			result.setData(null);
			MarvelsLogUtil.getInstance().error("注册失败", e);
		}

		return result;
	}
	
	@Override
	public JsonResult<User> exchangPwd(User user) {
		JsonResult<User> result = new JsonResult<User>();
		if (null == user || StringUtils.isEmpty(user.getMobileNo())) {
			result.setErrorMsg(ReturnCode.fail.getErrorCode(), "手机号为空!");
			return result;
		}

		if (null == user || StringUtils.isEmpty(user.getPassWord())) {
			result.setErrorMsg(ReturnCode.fail.getErrorCode(), "新密码为空!");
			return result;
		}
		if (!smsService.checkCode(user.getMobileNo(), user.getValidCode(), SmsTypeEnum.REGISTER.getName())) {
			result.setErrorMsg(ReturnCode.fail.getErrorCode(), "验证码不正确!");
			return result; 
		}
		
		try {
			User userTemp = userService.queryUserByMobileNo(user.getMobileNo(), "2");
			User userEntity = new User();
			userEntity.setIdFintechUmUser(userTemp.getIdFintechUmUser());
			userEntity.setPassWord(user.getPassWord());
			int res = userService.updatePwd(userEntity);
			if (res > 0) {
				result.setErrorMsg(ReturnCode.success.getErrorCode(), "新密码设置成功!");
			} else {
				result.setErrorMsg(ReturnCode.fail.getErrorCode(), "新密码设置失败!");
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("更新密码操作异常", e);
			result.setErrorMsg(ReturnCode.fail.getErrorCode(), "新密码设置失败!");
		}

		return result;
	}
	
	@Override
	public FintechResult addYdCallTimes(Map<String, String> map, User user) {
		MarvelsLogUtil.getInstance().info("======有盾实名认证和人脸视别调用计费统计，参数:" + JSON.toJSONString(map));
		try {
			if (map == null || StringUtils.isEmpty(map.get("identityCardNo"))) {
				return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "统计信息为空");
			}
			String reqNo = "YD_" + System.currentTimeMillis() + "_" + RandomStringUtils.randomAlphanumeric(6);
			baseServiceUtil.saveDataQueryLogNew(reqNo, null, user.getMobileNo(), null, new Date(),
					"YD0002", map.get("responseCode"), "1", "edc_yd_data_query_log", map.get("identityCardNo"));

			MarvelsLogUtil.getInstance().info("======有盾实名认证和人脸视别调用计费统计入库成功");
			return FintechResult.getSuccessResult(null);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("有盾实名认证和人脸视别调用计费统计入库异常, map=[" + JSON.toJSONString(map) + "]", e);
			return FintechResult.getFailResult(ReturnCode.fail.getErrorCode(), "有盾实名认证和人脸视别调用计费统计入库异常");
		}
	}
	
	private void freshUser(RealNameAuthentication realNameAuthentication, User user) {
		MarvelsLogUtil.getInstance().info("========freshUser========");
		if (user != null && realNameAuthentication != null) {
			user.setCardNo(realNameAuthentication.getIdentityCardNo());
			user.setRealName(realNameAuthentication.getRealName());
			user.setRealNameAuthentication(true);
			user.setFaceCheck(true);
			user.setIsVerify(1);
			user.setIsFace(1);
			MarvelsLogUtil.getInstance().info("========freshUser========,user=" + JSON.toJSONString(user));
			RedisUtils.getInstance().setex(user.getIdFintechUmUser(), 15 * 24 * 60 * 60, JSON.toJSONString(user));
		}
	}
	
	private void saveImg(String pictureBase64, String mobileNo) {
		String prefix = FileUtils.getPathPrefix();
		String fileName = System.currentTimeMillis() + mobileNo;
		String pathPrefix = FileUtils.getValueByPropertiesKey("nfs.file.system");
		String filePath = pathPrefix + prefix + File.separator + fileName + "renlian.png";
		List<CmAttachment> cmAttachments = new ArrayList<CmAttachment>();
		File file = new File(filePath);
		ImageUtils.base64ToImg(pictureBase64, file);

		MarvelsLogUtil.getInstance().info("========人脸识别上传照片完美通过========" + mobileNo);

		// 保存附件表
		CmAttachment cmAttachment = new CmAttachment();
		cmAttachment.setAtmtType("R");
		cmAttachment.setFileLocation(filePath);
		cmAttachment.setLoanId(mobileNo);
		cmAttachment.setUploadTime(new Date());
		cmAttachments.add(cmAttachment);
		cmAttachmentService.insertMsg(cmAttachments);
		
		MarvelsLogUtil.getInstance().info("========附件表保存成功========");
	}


	@Override
	public boolean verifySlideCode(Map<String, String> param) {
		String captchaId  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.captchaid");
		String secretId  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.secretid");
		String secretKey  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.secretkey");
		String requestUrl  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.request.url");
		NECaptchaVerifier verifier = new NECaptchaVerifier(captchaId, new NESecretPair(secretId, secretKey));
		boolean verify = false;
		try {
			String user = param.get("user");
			String validate = param.get("NECaptchaValidate"); // 二次验证带过来的数据
			// 开始提交到易盾做二次校验，以确保该次验证时有效并且是最近完成的
			verify = verifier.verify(validate, user, requestUrl);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("滑块验证码验证时出现异常", e);
			return verify;
		}
		return verify;
	}


	@Override
	public boolean verifySlideCode(SendSMSDTO param) {
		String captchaId  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.captchaid");
		String secretId  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.secretid");
		String secretKey  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.secretkey");
		String requestUrl  = ServerProperties.getValue(configPropertiesPath, "common.properties", "yidun.request.url");
		NECaptchaVerifier verifier = new NECaptchaVerifier(captchaId, new NESecretPair(secretId, secretKey));
		boolean verify = false;
		try {
			String user = param.getUser();
			String validate = param.getNeCaptchaValidate(); // 二次验证带过来的数据
			// 开始提交到易盾做二次校验，以确保该次验证时有效并且是最近完成的
			verify = verifier.verify(validate, user, requestUrl);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("滑块验证码验证时出现异常", e);
			return verify;
		}
		return verify;
	}


	@Override
	public Map<String, String> isProhibitZrllApply(Integer userId, String channelCode) {
		Map<String, String> result = new HashMap<String, String>();
		result.put("code", "0");
		// 禁止自然流量申请的配置
		Map<String, String> applyConfig = acLoanApplyInfoRepository.getAppConfigByKey("prohibit.zrll.apply");
		if(applyConfig != null && "0".equals(applyConfig.get("state").toString())){
			if (StringUtils.isNotEmpty(channelCode)) {
				//校验渠道号
				UserChannelInfo userChannelInfo = userChannelInfoService.selectChannelInfoByCode(channelCode);
				if(userChannelInfo == null || userChannelInfo.getStatus() == 0){
					// 失效的渠道，算作自然流量
					result.put("code", "-1");
					result.put("msg", applyConfig.get("config_value"));
				}
			}else{
				result.put("code", "-1");
				result.put("msg", applyConfig.get("config_value"));
			}
		}
		
		// 如果开关确实是打开的，那么再去查看这个人是否有历史进单
		if("-1".equals(result.get("code")) && userId != null){
			RealNameAuthentication realNameAuthentication = realNameAuthenticationService.queryByUserId(userId);
			if (realNameAuthentication != null) {
				// 开关对老客户不生效
				Integer loanNumber = mcamLoanApplyInfoDao.querySettleLoan(realNameAuthentication.getIdentityCardNo());
				if(loanNumber > 0){
					result.put("code", "0");
				}
			}
		}
		return result;
	}

}
